package fem2d;

import math2.FunctionRnToR;
import fem2.AbstractStructuralStaticDemo;
import fem2.Debugger;
import fem2.MaterialModel;
import fem2.Model;
import fem2.analysis.Analysis;
import fem2.analysis.NonlinearStaticAnalysis;
import fem2.enu.EchoLevelType;
import fem2.enu.State;
import fem2.material.ExponentialSofteningRule;
import fem2.material.FluencyCriteria;
import fem2.material.IsotropicDamageMMimplexNonlocal;
import fem2.mesh_and_topology.IntegrationPointIndexer;
import fem2.observer.TimeStepObserver;
import fem2.strategies.Strategy;

public class NotchBeamIsotropicDamageImplexNonlocal extends NotchBeamIsotropicDamage {

	public NotchBeamIsotropicDamageImplexNonlocal() {
		projectDir = "/home/hbui/kratos_janosch";
		projectName = "notchbeam.gid";
		// meshFileName = "mesh1-damage-implex-nonlocal.msh";
		meshFileName = "mesh2-damage-implex-nonlocal.msh";
	}

	@Override
	public MaterialModel createMaterial(Model m) {
		double E = 2;
		double nu = 0.3;
		double t = 1.0;
		double ft = 0.91;
		// double Gf = 0.065;

		double e0 = ft / Math.sqrt(E);
		// double ef = Gf / ft;
		// double ef = 3 * e0;
		double ef = 100 * e0;
		FluencyCriteria softeningRule = new ExponentialSofteningRule(e0, ef);

		// final double interactionRadius = 0.5;//for mesh 1
		// final double interactionRadius = 0.1; // for mesh 2;
		final double interactionRadius = 0.05; // for mesh 2;
		FunctionRnToR weightFunction = new FunctionRnToR() {

			@Override
			public double valueAt(double... x) {
				if (x[0] < interactionRadius && x[0] >= 0.0) {
					return Math.pow(1 - Math.pow(x[0] / interactionRadius, 2), 2);
				} else {
					return 0;
				}
			}

			@Override
			public double[] gradientAt(double... x) {
				return null;
			}
		};

		return new IsotropicDamageMMimplexNonlocal(E, nu, 0, t, State.PLANE_STRAIN, softeningRule,
				e0, weightFunction, interactionRadius, new IntegrationPointIndexer(m.getMesh()));

	}

	// @Test
	// public void testIndexing() {
	// Model m = createModel();
	//
	// IntegrationPointSpatialIndexer idx = new
	// IntegrationPointSpatialIndexer(m);
	//
	// idx.indexing();
	//
	// Map<Element, ArrayList<Integer>> list = idx.queryRange(new
	// SphereSpatialCriteria(0.95, 0.5,
	// 0.5));
	//
	// for (Element e : list.keySet()) {
	// ArrayList<Integer> gps = list.get(e);
	// Debugger.watch("Element: " + e.getId());
	// Debugger.watch(gps);
	// for (int i : gps) {
	// Debugger.watch(e.getMeshPart().XAt(e.getIntegrationPoint(i)));
	// }
	// }
	// }

	@Override
	public void run(int nt) {
		Model m = createModel();

		Analysis an = new NonlinearStaticAnalysis(m, nt);
		Strategy s = an.getStrategy();
		s.setEchoLevel(EchoLevelType.OUTPUT, EchoLevelType.AUX1);

		addObservers(m, s, new TimeStepObserver(s));

		an.run();

		// postProcess(m);

		Debugger.warn("Analysis completed");
	}

	public static void main(String[] args) {
		AbstractStructuralStaticDemo demo = new NotchBeamIsotropicDamageImplexNonlocal();
		//
		// demo.run(60);
		// demo.run(200);
		demo.run(500);
		// demo.run(1000);
	}
}
